package top.jolyoulu.mytomcat;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @Author LuZhouJin
 * @Date 2023/8/4
 */
public class MyTomcat {
    private int port = 8080;
    private ServerSocket server;
    private Map<String, MyServlet> servletMapping = new HashMap<>();
    private Properties webxml = new Properties();

    private void init() {
        try {
            //加载web.xml 这里使用mytomcat.properties替代
            String WEB_INF = this.getClass().getResource("/").getPath();
            FileInputStream fis = new FileInputStream(WEB_INF + "mytomcat.properties");

            webxml.load(fis);

            for (Object k : webxml.keySet()) {
                String key = k.toString();
                if (key.endsWith(".url")) {
                    String servletName = key.replaceAll("\\.url$", "");
                    String url = webxml.getProperty(key);
                    String className = webxml.getProperty(servletName + ".className");
                    //单实例，多线程
                    MyServlet o = (MyServlet) Class.forName(className).newInstance();
                    servletMapping.put(url, o);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void start(){
        //加载配置忘记，初始化 servletMapping
        init();

        //Boss 线程
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        //Worker 线程
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //创建服务
            ServerBootstrap server = new ServerBootstrap();
            //参数配置
            server.group(bossGroup,workerGroup)
                    //主线程处理类
                    .channel(NioServerSocketChannel.class)
                    //子现场处理类，Handler
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        //客户端初始化处理
                        @Override
                        protected void initChannel(SocketChannel client) throws Exception {
                            //Netty对HTTP的封装，对顺序有要求
                            //HttpResponseEncoder 编码器
                            client.pipeline().addLast(new HttpResponseEncoder());
                            //HttpRequestDecoder 解码器
                            client.pipeline().addLast(new HttpRequestDecoder());
                            //自己的业务处理器
                            client.pipeline().addLast(new MyTomcatHandler());
                        }
                    })
                    //针对主线程的配置，分配线程最大数量 128
                    .option(ChannelOption.SO_BACKLOG,128)
                    //针对子线程配置 保存长连接
                    .childOption(ChannelOption.SO_KEEPALIVE,true);

            //启动服务器
            ChannelFuture f = server.bind(port).sync();
            System.out.println("MyTomcat 已启动，监听端口："+this.port);
            f.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public class MyTomcatHandler extends ChannelInboundHandlerAdapter{
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if (msg instanceof HttpRequest){
                System.out.println("hello");
                HttpRequest req = (HttpRequest) msg;
                //转交给我们自己的Request实现
                MyRequest request = new MyRequest(ctx, req);
                //转交给我们自己的Response实现
                MyResponse response = new MyResponse(ctx, req);
                //实际业务处理
                String url = request.getUrl();
                if (servletMapping.containsKey(url)){
                    servletMapping.get(url).service(request,response);
                }else {
                    response.write("404 - Not Found");
                }
            }
        }
    }

    public static void main(String[] args) {
        new MyTomcat().start();
    }

}
